﻿package src {
	import flash.display.*;
	
	/**
	 * To represent one motif match
	 * @author Indrek Tamming
	 */
	public class MotifMatch extends Sprite {
		
		/**
		 * The index of sequence the match is on
		 */
		private var sequenceNumber:int;
		
		/**
		 * The strand of the match
		 */
		private var strand:int;
		
		/**
		 * Match begin index
		 */
		private var beginIndex:int;
		
		/**
		 * Match end index
		 */
		private var endIndex:int;
		
		/**
		 * Match score
		 */
		private var densityScore:Number;
		
		/**
		 * Match color
		 */
		private var matchColor:uint;
		
		/**
		 * Callback to MotifMatches
		 */
		private var matches:MotifMatches;
		
		public function MotifMatch(sequenceNumber:int, strand:int, beginIndex:int, endIndex:int, densityScore:Number):void {
			this.sequenceNumber = sequenceNumber;
			this.strand = strand;
			this.beginIndex = beginIndex;
			this.endIndex = endIndex;
			this.densityScore = densityScore;
		}
		
		/**
		 * Draw the match
		 * @param	zoomLevel	-	current zoom level
		 * @param	matches		-	callback to MotiofMatches
		 * @param	fillAlpha	-	fill's alpha value
		 * @param	letterSize	-	letter size
		 */
		public function draw(zoomLevel:int, matches:MotifMatches, fillAlpha:Number, letterSize:Number):void {
			this.matches = matches;
			this.matchColor = matches.getColor();
			
			while (this.numChildren > 0) this.removeChildAt(0); // if redrawn, clear the area
			var g:Graphics = this.graphics;
			g.clear(); // if redrawn, clear the area
			
			//var matchHeight:Number = 5 + densityScore;
			//var matchHeight:Number = calculateHeight(zoomLevel, matches.getMinScore(), matches.getMaxScore());
			var matchHeight:Number = calculateHeight(zoomLevel, matches.getFilter(), matches.getMaxScore());
			var matchWidth:Number = letterSize * (endIndex - beginIndex + 1);
			
			if(zoomLevel <= 2) {
				g.beginFill(matchColor, fillAlpha);
				g.drawRect(0, strand>0 ? -matchHeight : letterSize, matchWidth, matchHeight);
				g.endFill();
				
				g.lineStyle(1.33, matchColor, 1, false, "normal", CapsStyle.NONE); // try ROUND
				g.moveTo(0, strand>0 ? 0 : letterSize);
				g.lineTo(0, strand>0 ? -matchHeight : letterSize + matchHeight);
				g.lineTo(matchWidth, strand>0 ? -matchHeight : letterSize + matchHeight);
				g.lineTo(matchWidth, strand > 0 ? 0 : letterSize);
			}
			else {
				var _match:Shape = new Shape();
				g = _match.graphics;
				g.beginFill(matchColor, fillAlpha);
				g.drawRect(0, strand>0 ? -matchHeight : letterSize, matchWidth, matchHeight);
				g.endFill();
				g.lineStyle(0.66, matchColor, 1, false, "normal", CapsStyle.NONE);
				g.moveTo(0, strand>0 ? 0 : letterSize);
				g.lineTo(0, strand>0 ? -matchHeight : letterSize + matchHeight);
				g.lineTo(matchWidth, strand>0 ? -matchHeight : letterSize + matchHeight);
				g.lineTo(matchWidth, strand > 0 ? 0 : letterSize);
				//g = this.graphics;
				_match.y = -0.5;
				addChild(_match);
			}
			
			//cacheAsBitmap = true;
		}
		
		/**
		 * Calculate matches height
		 * @param	zoomLevel	-	current zoom level
		 * @param	minScore	-	minimum score
		 * @param	maxScore	-	maximum score
		 * @return	the number with height value
		 */
		private function calculateHeight(zoomLevel:int, minScore:Number, maxScore:Number):Number {
			var range:Number = maxScore - minScore;
			var rangeUnit:Number = range * 0.25;
			var currentRange:int;
			
			if (densityScore < rangeUnit) currentRange = 1;
			else if (densityScore < 2 * rangeUnit) currentRange = 2;
			else if (densityScore < 3 * rangeUnit) currentRange = 3;
			else currentRange = 4;
			
			var height:Number;
			switch(zoomLevel) {
				case 1:
					height = 4 * currentRange;
					//height = Math.exp(currentRange/1.5) + 2;
					
					break;
				case 2:
					height = 3 * currentRange;
					//height = Math.exp(currentRange/1.75) + 2;
					break;
				case 3:
					height = 2 * currentRange;
					break;
				case 4:
					height = 2 * currentRange;
					break;
				default: 
					height = 0;
					break;
			}
			return height;
		}
		
		/**
		 * Get sequence number
		 * @return
		 */
		public function getSequenceNumber():int {
			return sequenceNumber;
		}
		
		/**
		 * Get strand
		 * @return
		 */
		public function getStrand():int {
			return strand;
		}
		
		/**
		 * Get begin index
		 * @return
		 */
		public function getBeginIndex():int {
			return beginIndex;
		}
		
		/**
		 * Get end index
		 * @return
		 */
		public function getEndIndex():int {
			return endIndex;
		}
		
		/**
		 * Get score
		 * @return
		 */
		public function getScore():Number {
			return densityScore;
		}
		
		/**
		 * Get color
		 * @return
		 */
		public function getColor():uint {
			return matches.getColor();
		}
		
		/**
		 * Get the Motif object
		 * @return
		 */
		public function getMotif():Motif {
			return matches.getMotif();
		}
		
		/**
		 * Get the MotifMatches object
		 * @return
		 */
		public function getMatches():MotifMatches {
			return matches;
		}
		
	}
	
}